package com.csii.modules.system.controller;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.csii.core.api.Result;
import com.csii.core.constant.CommonConstant;
import com.csii.core.system.vo.LoginUser;
import com.csii.core.system.vo.TokenPassword;
import com.csii.core.util.MD5Util;
import com.csii.core.util.RedisUtil;
import com.csii.core.util.encryption.AesEncryptUtil;
import com.csii.core.util.oConvertUtils;
import com.csii.modules.system.model.SysLoginModel;
import com.csii.modules.system.service.ISysBaseAPI;
import com.csii.modules.system.service.ISysDictService;
import com.csii.modules.system.service.ISysLogService;
import com.csii.modules.system.util.RandImageUtil;
import com.csii.user.entity.SysDepart;
import com.csii.user.service.ISysUserBaseService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * @Author ian
 * @since 2018-12-17
 */
@RestController
@RequestMapping("/sys")
@Api(tags="用户登录")
@Slf4j
public class LoginController {
	@Autowired
	private ISysBaseAPI sysBaseAPI;
	@Autowired
	private ISysLogService logService;
	@Autowired
    private RedisUtil redisUtil;
	@Autowired
    private ISysUserBaseService sysUserServiceFeign;
	@Autowired
    private ISysDictService sysDictService;
	@Value("${authorization.clientId}")
	private String clientId;
	@Value("${authorization.clientSecret}")
	private String clientSecret;
	@Autowired
	private RedisTemplate redisTemplate;

	private final Snowflake snowflake = new Snowflake(1,10);

	private static final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";

	/**
	 * code登录统一认证
	 * @param ticket
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	@GetMapping("/token/")
	public Result tokenInfo(@RequestParam String ticket,@RequestParam String service,@RequestParam(required = false) String clientId) throws UnsupportedEncodingException {
		//获取token
		Map tokenMap = getAccessToken(ticket,service,StringUtils.isEmpty(clientId)?this.clientId:clientId);
		LoginUser loginUser=LoginUser.build(tokenMap);
		Map<String,Object> result= new HashMap<>();
		result.put("userInfo",loginUser);
		result.put("token",tokenMap.get("access_token"));
		return Result.ok(result);
	}

	/**
	 * password登录统一认证
	 * @param tokenPassword
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	@PostMapping("/token/password")
	public Result tokenPassword(@RequestBody TokenPassword tokenPassword) throws UnsupportedEncodingException {
		try {
			Map tokenJson=getAccessTokenPassword(tokenPassword.getUsername(),tokenPassword.getPassword(),clientId);
			LoginUser loginUser=LoginUser.build(tokenJson);
			//生成openId
			String openId = (String) redisTemplate.opsForValue().get(loginUser.getId());
			//判断openId 是否存在 , 存在就清除,生成新的openId
			if (openId != null){
				redisTemplate.delete(openId);
			}
			openId = snowflake.nextIdStr();
			redisTemplate.opsForValue().set(loginUser.getId(),openId);
			redisTemplate.opsForValue().set(openId,loginUser.getId());
			loginUser.setOpenId(openId);
			Map<String,Object> result= new HashMap<>();
			result.put("userInfo",loginUser);
			result.put("token",tokenJson.get("access_token"));
			return Result.ok(result);
		}catch (HttpClientErrorException e){
			Result<Object> errorResult = new Result<>();
			errorResult.error500("用户名或密码错误");
			return errorResult;
		}
	}

	/**
	 * 获取token
	 */
	public Map getAccessToken(String code,String service,String clientId) throws UnsupportedEncodingException {
		String encode ="Basic " + Base64.encode(clientId + ":" + clientSecret);
		return sysUserServiceFeign.loginByCode("authorization_code",code,service,encode);
	}
	public Map getAccessTokenPassword(String username,String password,String clientId) throws UnsupportedEncodingException {
		String encode ="Basic " + Base64.encode(clientId + ":" + clientSecret);
		return sysUserServiceFeign.loginByPassword("password",username,password,encode);
	}


	@ApiOperation("登录接口")
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public Result<JSONObject> login(@RequestBody SysLoginModel sysLoginModel){
		Result<JSONObject> result = new Result<JSONObject>();
		String username = sysLoginModel.getUsername();
		String password = sysLoginModel.getPassword();
		Map<String, String> user = sysUserServiceFeign.loginByPassword("password", username, password, "");
		if (!StringUtils.isEmpty(user.get("error")) ) {
			result.error500("用户名或密码错误");
			return result;
		}else {
			LoginUser loginUser=new LoginUser();
			loginUser.setRealname(user.get("nickName"));
			loginUser.setUsername(user.get("userName"));
			loginUser.setId(user.get("userId"));
			loginUser.setEmail(user.get("email"));
			loginUser.setPhone(user.get("phone"));
			//用户登录信息
			userInfo(loginUser, result);
			sysBaseAPI.addLog("用户名: " + username + ",登录成功！", CommonConstant.LOG_TYPE_1, null);
		}
		return result;
	}
	
	/**
	 * 退出登录
	 * @param request
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "/logout")
	public Result<Object> logout(HttpServletRequest request, HttpServletResponse response) {
		//用户退出逻辑
	    /*String token = request.getHeader(CommonConstant.OAUTH_USER_INFO);
	    if(oConvertUtils.isEmpty(token)) {
	    	return Result.error("退出登录失败！");
	    }
	    String username = JwtUtil.getUsername(token);
		LoginUser sysUser = sysBaseAPI.getUserByName(username);
	    if(sysUser!=null) {
	    	sysBaseAPI.addLog("用户名: "+sysUser.getRealname()+",退出成功！", CommonConstant.LOG_TYPE_1, null);
	    	log.info(" 用户名:  "+sysUser.getRealname()+",退出成功！ ");
	    	//清空用户登录Token缓存
	    	redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
	    	//清空用户登录Shiro权限缓存
			redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());
			//清空用户的缓存信息（包括部门信息），例如sys:cache:user::<username>
			redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()));
			//调用shiro的logout
			SecurityUtils.getSubject().logout();*/
	    	return Result.ok("退出登录成功！");
	   /* }else {
	    	return Result.error("Token无效!");
	    }*/
	}
	
	/**
	 * 获取访问量
	 * @return
	 */
	@GetMapping("loginfo")
	public Result<JSONObject> loginfo() {
		Result<JSONObject> result = new Result<JSONObject>();
		JSONObject obj = new JSONObject();
		//update-begin--Author:zhangweijian  Date:20190428 for：传入开始时间，结束时间参数
		// 获取一天的开始和结束时间
		Calendar calendar = new GregorianCalendar();
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		Date dayStart = calendar.getTime();
		calendar.add(Calendar.DATE, 1);
		Date dayEnd = calendar.getTime();
		// 获取系统访问记录
		Long totalVisitCount = logService.findTotalVisitCount();
		obj.put("totalVisitCount", totalVisitCount);
		Long todayVisitCount = logService.findTodayVisitCount(dayStart,dayEnd);
		obj.put("todayVisitCount", todayVisitCount);
		Long todayIp = logService.findTodayIp(dayStart,dayEnd);
		//update-end--Author:zhangweijian  Date:20190428 for：传入开始时间，结束时间参数
		obj.put("todayIp", todayIp);
		result.setResult(obj);
		result.success("登录成功");
		return result;
	}
	
	/**
	 * 获取访问量
	 * @return
	 */
	@GetMapping("visitInfo")
	public Result<List<Map<String,Object>>> visitInfo() {
		Result<List<Map<String,Object>>> result = new Result<List<Map<String,Object>>>();
		Calendar calendar = new GregorianCalendar();
		calendar.set(Calendar.HOUR_OF_DAY,0);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);
        calendar.set(Calendar.MILLISECOND,0);
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        Date dayEnd = calendar.getTime();
        calendar.add(Calendar.DAY_OF_MONTH, -7);
        Date dayStart = calendar.getTime();
        List<Map<String,Object>> list = logService.findVisitCount(dayStart, dayEnd);
		result.setResult(oConvertUtils.toLowerCasePageList(list));
		return result;
	}
	


	/**
	 * 手机号登录接口
	 * 
	 * @param jsonObject
	 * @return
	 */
	@ApiOperation("手机号登录接口")
	@PostMapping("/phoneLogin")
	public Result<JSONObject> phoneLogin(@RequestBody JSONObject jsonObject) {
		Result<JSONObject> result = new Result<JSONObject>();
		/*String phone = jsonObject.getString("mobile");
		
		//校验用户有效性
		SysUser sysUser = sysUserService.getUserByPhone(phone);
		result = sysUserService.checkUserIsEffective(sysUser);
		if(!result.isSuccess()) {
			return result;
		}
		
		String smscode = jsonObject.getString("captcha");
		Object code = redisUtil.get(phone);
		if (!smscode.equals(code)) {
			result.setMessage("手机验证码错误");
			return result;
		}
		//用户信息
		userInfo(sysUser, result);*/
		//添加日志
		sysBaseAPI.addLog("用户名: ,登录成功！", CommonConstant.LOG_TYPE_1, null);

		return result;
	}


	/**
	 * 用户信息
	 *
	 * @param sysUser
	 * @param result
	 * @return
	 */
	private Result<JSONObject> userInfo(LoginUser sysUser, Result<JSONObject> result) {

		// 获取用户部门信息
		JSONObject obj = new JSONObject();
		Result<List<SysDepart>> departs =sysUserServiceFeign.listUserDepartList(sysUser.getId());
		obj.put("departs", departs.getResult());
		if (departs == null || departs.getResult().size() == 0) {
			obj.put("multi_depart", 0);
		} else if (departs.getResult().size() == 1) {
			obj.put("multi_depart", 1);
		} else {
			obj.put("multi_depart", 2);
		}
		obj.put("userInfo", sysUser);
		obj.put("sysAllDictItems", sysDictService.queryAllDictItems());
		result.setResult(obj);
		result.success("登录成功");
		return result;
	}

	/**
	 * 获取加密字符串
	 * @return
	 */
	@GetMapping(value = "/getEncryptedString")
	public Result<Map<String,String>> getEncryptedString(){
		Result<Map<String,String>> result = new Result<Map<String,String>>();
		Map<String,String> map = new HashMap<String,String>();
		map.put("key", AesEncryptUtil.KEY);
		map.put("iv", AesEncryptUtil.IV);
		result.setResult(map);
		return result;
	}

	/**
	 * 后台生成图形验证码 ：有效
	 * @param response
	 * @param key
	 */
	@ApiOperation("获取验证码")
	@GetMapping(value = "/randomImage/{key}")
	public Result<String> randomImage(HttpServletResponse response, @PathVariable String key){
		Result<String> res = new Result<String>();
		try {
			String code = RandomUtil.randomString(BASE_CHECK_CODES,4);
			String lowerCaseCode = code.toLowerCase();
			String realKey = MD5Util.MD5Encode(lowerCaseCode+key, "utf-8");
			redisUtil.set(realKey, lowerCaseCode, 60);
			String base64 = RandImageUtil.generate(code);
			res.setSuccess(true);
			res.setResult(base64);
		} catch (Exception e) {
			res.error500("获取验证码出错"+e.getMessage());
			e.printStackTrace();
		}
		return res;
	}
	
	/**
	 * app登录
	 * @param sysLoginModel
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/mLogin", method = RequestMethod.POST)
	public Result<JSONObject> mLogin(@RequestBody SysLoginModel sysLoginModel) throws Exception {
		Result<JSONObject> result = new Result<JSONObject>();

		return result;
	}

	/**
	 * 图形验证码
	 * @param sysLoginModel
	 * @return
	 */
	@RequestMapping(value = "/checkCaptcha", method = RequestMethod.POST)
	public Result<?> checkCaptcha(@RequestBody SysLoginModel sysLoginModel){
		String captcha = sysLoginModel.getCaptcha();
		String checkKey = sysLoginModel.getCheckKey();
		if(captcha==null){
			return Result.error("验证码无效");
		}
		String lowerCaseCaptcha = captcha.toLowerCase();
		String realKey = MD5Util.MD5Encode(lowerCaseCaptcha+checkKey, "utf-8");
		Object checkCode = redisUtil.get(realKey);
		if(checkCode==null || !checkCode.equals(lowerCaseCaptcha)) {
			return Result.error("验证码错误");
		}
		return Result.ok();
	}

}